﻿Imports System
Imports System.CodeDom
Imports System.Collections
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization

Namespace System.Workflow.ComponentModel.Serialization
    Friend NotInheritable Class SerializableTypeCodeDomSerializer
        Inherits CodeDomSerializer
        ' Methods
        Public Sub New(ByVal originalSerializer As CodeDomSerializer)
            If (originalSerializer Is Nothing) Then
                Throw New ArgumentNullException("originalSerializer")
            End If
            Me.originalSerializer = originalSerializer
        End Sub

        Private Function AddVariableExpression(ByVal manager As IDesignerSerializationManager, ByVal statements As CodeStatementCollection, ByVal value As Object) As CodeVariableReferenceExpression
            Dim name As String = MyBase.GetUniqueName(manager, value).Replace("`"c, "_"c)
            Dim statement As New CodeVariableDeclarationStatement(TypeDescriptor.GetClassName(value), name) { _
                .InitExpression = New CodeObjectCreateExpression(TypeDescriptor.GetClassName(value), New CodeExpression(0  - 1) {}) _
            }
            statements.Add(statement)
            Dim expression As New CodeVariableReferenceExpression(name)
            MyBase.SetExpression(manager, value, expression)
            Return expression
        End Function

        Public Overrides Function Serialize(ByVal manager As IDesignerSerializationManager, ByVal value As Object) As Object
            If (manager Is Nothing) Then
                Throw New ArgumentNullException("manager")
            End If
            Dim obj2 As Object = Nothing
            If (Not value Is Nothing) Then
                Dim statements As CodeStatementCollection = Nothing
                Dim context As ExpressionContext = [TryCast](manager.Context.Item(GetType(ExpressionContext)),ExpressionContext)
                If (Not value.GetType.GetConstructor(New Type(0  - 1) {}) Is Nothing) Then
                    If TypeOf value Is ICollection Then
                        Dim context2 As ExpressionContext = Nothing
                        If (context Is Nothing) Then
                            Return obj2
                        End If
                        If (Not context.PresetValue Is value) Then
                            Try 
                                statements = New CodeStatementCollection
                                Dim expression As CodeVariableReferenceExpression = Me.AddVariableExpression(manager, statements, value)
                                context2 = New ExpressionContext(expression, value.GetType, context.Owner, value)
                                manager.Context.Push(context2)
                                obj2 = Me.originalSerializer.Serialize(manager, value)
                                If TypeOf obj2 Is CodeStatementCollection Then
                                    statements.AddRange([TryCast](obj2,CodeStatementCollection))
                                    Return statements
                                End If
                                If TypeOf obj2 Is CodeStatement Then
                                    statements.Add([TryCast](obj2,CodeStatement))
                                    Return statements
                                End If
                                If TypeOf obj2 Is CodeExpression Then
                                    statements.Add(New CodeAssignStatement(expression, [TryCast](obj2,CodeExpression)))
                                End If
                                Return statements
                            Finally
                                If (Not context2 Is Nothing) Then
                                    manager.Context.Pop
                                End If
                            End Try
                        End If
                        Return Me.originalSerializer.Serialize(manager, value)
                    End If
                    statements = New CodeStatementCollection
                    Me.AddVariableExpression(manager, statements, value)
                    MyBase.SerializeProperties(manager, statements, value, New Attribute() { DesignOnlyAttribute.No })
                    MyBase.SerializeEvents(manager, statements, value, New Attribute() { DesignOnlyAttribute.No })
                    Return statements
                End If
                If (Not context Is Nothing) Then
                    obj2 = Me.originalSerializer.Serialize(manager, value)
                End If
            End If
            Return obj2
        End Function


        ' Fields
        Private originalSerializer As CodeDomSerializer
    End Class
End Namespace

